/**
 *  输入输出
 */
#include <stdio.h>
#include <stdlib.h>
#include "card.h"
#include "stdint.h"

#include "Recursion.h"
#include "var.h"


#define LENGTH(array)(sizeof(array)/sizeof(array[0]))
typedef unsigned char bool_t;
typedef unsigned char BOOL;
#define OTHER_DEBUG_USART 1
#define GPIO_BASE_ADDR(x)							(0x40004000 + 0x0400 * (x))
#define REG_GPIO_IDATA(x)	(*(volatile uint32_t *)(GPIO_BASE_ADDR(x) + 0x14))
BOOL gsm_init_flg;
#define	OTHER_DEBUG_USART 1
uint8_t keyDownCnt;


//输入输出
void ioTest();

void ioTestChar();

void ioTestGetsAndPuts();

void ioTestN();

void base();

void testPointerArray();

void pointerFun();

void callbackFun();

void testEnum();

void testEnum1();

void testArray();

void testSscanf();

/**
 * ------------------宏的定义-------
 */
void testDefine(){
    Single x,y;
    Read("%f",&x);
    If(x>0){
        y=x;
    }Else{
        y=-x;
    };
    Write("%f",y);
}

void testDefine1(){

}



int main1()
{
    setvbuf(stdout, NULL, _IONBF, 0); //解决debug时，scanf优于printf捕获的问题
    base();
//    ioTest();
//    ioTestChar();
//    ioTestGetsAndPuts();
    // ioTestN();
    testPointerArray();

    //init();
//    init_iot_card();
    // 连接到服务器
//    send_at_command("AT+CIPSTART=TCP,your_server_ip,your_server_port\r\n");
    // 需要等待'CONNECT OK'或'CONNECT FAIL'响应
    // 这里省略了等待响应的代码

    // 发送数据
//    const char *message = "Hello, Internet of Things!\n";
//    send_data(message); // 发送数据
    //pointerFun();

    callbackFun();
    testEnum();
    //testEnum1();
    testArray();
    testSscanf();



    //printf("%d \n",f(5));
    printRecursion();

    uint8_t isflag;

    bool_t testFlag;
    printf("testflag=%d\n", testFlag);

    printf("%d", isflag);
    printf("%d", !isflag);
    isflag = 1;
    if (isflag)
    {
        printf("test\n");
    }


#if OTHER_DEBUG_USART
    printf("测试-0 \n");
#endif

    if(1){
        printf("1 \n");
    }else{
        printf("0"); //永遠不會執行到
    }

    printf("keydowncnt=%d\n",keyDownCnt);

    printf("%d \n", ((0x40004000 + 0x0400 * (8))>>3)&0x01);

    uint8_t bnum=0;
    printf("%d \n",bnum);
//    while(0){ //不执行循环体的操作
//        printf("11111 \n");
//    }

//#if OTHER_DEBUG_USART
//    printf("\r\nLevel YXT20 build in %s %s\r\n");
//#endif

    //testDefine(); //宏定义
    return 0;
}

/**
 * 输入输出
 */
void ioTest()
{
    float f;

    printf("Enter a number: ");
    // %f 匹配浮点型数据
    scanf("%f", &f);
    printf("Value = %f\n", f);


//    int c;
//    printf("Enter a value: ");
//    c=getchar();
//    printf("\nYou entered: ");
//    putchar(c);
//    printf("\n");

}

/**
 * getchar(),putchar() 只会得到一个字符
 */
void ioTestChar()
{

    int c;
    printf("Enter a value: ");
    // while(getchar()!='\n'); // 清除之前的回车
    if (getchar() != '\n');
//    while((c = getchar())!="\n") {
//        printf("\nYou entered: ");
//
//        putchar(c);
//        printf("\n");
//    }
    c = getchar();
    printf("\nYou entered: ");
    putchar(c);
    printf("\n");
}


/**
 * 测试gets,puts
 */
//void ioTestGetsAndPuts()
//{
//    char str[100];
//    printf("enter a value: ");
//    if (gets(str) != '\n'); //while(gets(str)!='\n');从缓冲区读出有’\n’
//    gets(str);
//
//    printf("\n You entered: ");
//    puts(str);
//
//}

/**
 *
 */
void ioTestN()
{
    char ch, buff[20], str[20];
    int num, i = 0;
    printf("please enter a string:\n");
    while ((ch = getchar() != '\n'))
    {
        str[i] = ch;
        i++;
    }
    str[i] = '\0';
    i = 0;
    printf("please enter a string:\n");
    if (getchar() == '\n'); //接收
    while ((ch = getchar() != '\n'))
    {
        buff[i] = ch;
        i++;
    }
    buff[i] = '\0';
    printf("%s\n", str);
    printf("%s\n", buff);

}

/**
 * 测试数组
 */
void testArray()
{
    int array[] = {1, 2, 3, 4, 5};
    int length = LENGTH(array);
    printf("数组长度:%d\n", length);
}

/**
 * ，指针ptr 的类型是int*,它指向的类型是int，它被初始化为指向整型变量a。
 * 接下来的第3句中，指针ptr被加了1，编译器是这样处理的：它把指针ptr 的值加上了sizeof(int)，
 * 在32 位程序中，是被加上了4，因为在32 位程序中，int 占4 个字节。由于地址是用字节做单位的，故ptr
 * 所指向的地址由原来的变量a 的地址向高地址方向增加了4 个字节。由于char 类型的长度是一个字节，
 * 所以，原来ptr 是指向数组a 的第0 号单元开始的四个字节，此时指向了数组a 中从第4 号单元开始的四个字节。我们可以用一个指针和一个循环来遍历一个数组
 */
void testPointerArray()
{
//    int array[20]={0};
//    int *ptr=array;
//    for(int i=0;i<20;i++){
//        (*ptr)++;
//        ptr++;
//    }
    int arr[5] = {10, 20, 30, 40, 50};
    int len = sizeof(arr) / sizeof(arr[0]);//计算数组长度
    for (int i = 0; i < len; i++)
    {
        printf("根据下标索引，下标：%d,对应的元素地址：%d,对应的元素值是:%d\n", i, &arr[i], arr[i]);
    }

    //数组是一个整体，它的内存是连续的，那么我们可以直接通过首地址（数组名默认就是首地址）偏移来达到数组遍历的效果
    int value0 = *(arr); //arr默认指向数组的首地址，获取数组第一个元素的值
    int value1 = *(arr + 1);
    int value2 = *(arr + 2);
    int value3 = *(arr + 3);
    int value4 = *(arr + 4);

    printf("%d-%d-%d-%d-%d\n", value0, value1, value2, value3, value4);

    int *p = arr; //int *p=arr[0]  指针p指向数组的首地址
    printf("指针p的值：%d\n", *p);
    printf("指针p存储的地址:%d\n", p); //指针变量存储的是arr数组的地址
    printf("数组arr的地址: %d\n", &arr);
    printf("数组arr首地址:%d\n", &arr[0]);
    printf("数组的第2个地址:%d,对应的值为:%d\n", p + 1, *(p + 1));

    printf("使用指针进行遍历 \n");
    for (int i = 0; i < len; i++)
    {
        printf("数组下标索引:%d,对应的元素地址：%d,对应的元素值是:%d\n", i, p + i, *(p + i)); //指针不动，i在动
    }
    printf("-------第3种-----------\n");
    for (int i = 0; i < len; i++)
    {
        printf("遍历数组:%d \n", *p);
        p++;  //通过指针遍历数组，不推荐使用
    }

    printf("-------第4种-----------\n");

    for (int i = 0; i < len; i++)
    {
        printf("遍历数组:%d \n", p[i]); //第一个值为地址
    }

    printf("-------第5种-----------\n");

    for (int i = 0; i < len; i++)
    {
        printf("%d \n", *(arr + i));
    }

    printf("-------第6种-----------\n");
    //通过指针移动
    for (int *p = &arr[0]; p < &arr[len]; p++)
    {
        printf("%d ", *p);
    }
    printf("\n");

}

int max1(int x, int y)
{
    return x > y ? x : y;
}

/**
 * 指针函数
 * 函数指针是指向函数的指针变量。

    通常我们说的指针变量是指向一个整型、字符型或数组等变量，而函数指针是指向函数。

    函数指针可以像一般函数一样，用于调用函数、传递参数。

    函数指针类型的声明：

    typedef int (*fun_ptr)(int,int); //  声明一个指向同样参数、返回值的函数指针类型
 */
void pointerFun()
{
    /**函数指针的定义*/
    int (*p)(int, int) =&max1; //&可以省略
    int a, b, c, d;
    printf("请输入3个数字:");
    scanf("%d %d %d", &a, &b, &c);
    d = p(p(a, b), c);
    printf("%d \n", d);

}

/**
 * 回调函数
 * 函数指针作为某个函数的参数
    函数指针变量可以作为某个函数的参数来使用的，回调函数就是一个通过函数指针调用的函数。

    简单讲：回调函数是由别人的函数执行时调用你实现的函数。
    例:
    你到一个商店买东西，刚好你要的东西没有货，于是你在店员那里留下了你的电话，过了几天店里有货了，店员就打了你的电话，然后你接到电话后就到店里去取了货。在这个例子里，
    你的电话号码就叫回调函数，你把电话留给店员就叫登记回调函数，店里后来有货了叫做触发了回调关联的事件，店员给你打电话叫做调用回调函数，你到店里去取货叫做响应回调事件。
    实例中 populate_array() 函数定义了三个参数，其中第三个参数是函数的指针，通过该函数来设置数组的值。

    实例中我们定义了回调函数 getNextRandomValue()，它返回一个随机值，它作为一个函数指针传递给 populate_array() 函数。

    populate_array() 将调用 10 次回调函数，并将回调函数的返回值赋值给数组。
 */
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i = 0; i < arraySize; i++)
    {
        array[i] = (int) getNextValue; //通过外部回调，设置array数组的值 myarray[10]真实数组
    }
}

int getNextRandomValue()
{
    return rand();
}

void callbackFun()
{
    int myarray[10];
    populate_array(myarray, 10, getNextRandomValue);
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", myarray[i]);

    }
    printf("\n");
}

/**
 * 进制处理
 */
void base()
{
    int c = 1308;  //10进制
    int num = 0b1010;  //定义2进制
    int hex = 0x51c; //定义16进制
    int num1 = 015; //定义8进制
    int x = 178;

    printf("转16进制:%x \n", c);
    printf("转10进制:%d \n", hex);
    printf("转8进制: %o \n", c);
    printf("转2进制:%d\n", num);
    printf("输出8进制:%o\n", num1);
}

/**
 * 枚举
 */
enum DAY
{
    MON = 1, TUE, WED, THU, FRI, SAT, SUN
};

enum DAY1
{
    MON1 = 1, TUE1, WED1, THU1, FRI1, SAT1, SUN1
} day;

void testEnum()
{
//    enum DAY day;
//    day=WED;
//    printf("%d ",day);
//    printf("\n");

    for (day = MON1; day <= SUN1; day++)
    {
        printf("枚举元素:%d ", day);
    }
    printf("\n");
}

void testEnum1()
{
    enum color
    {
        red = 1, green, blue
    };

    enum color favorite_color;

    /* 用户输入数字来选择颜色 */
    printf("请输入你喜欢的颜色: (1. red, 2. green, 3. blue): ");
    scanf("%u", &favorite_color);

    /* 输出结果 */
    switch (favorite_color)
    {
        case red:
            printf("你喜欢的颜色是红色");
            break;
        case green:
            printf("你喜欢的颜色是绿色");
            break;
        case blue:
            printf("你喜欢的颜色是蓝色");
            break;
        default:
            printf("你没有选择你喜欢的颜色");
    }
}

/**
 * sscanf C 库函数 int sscanf(const char *str, const char *format, ...) 从字符串读取格式化输入。
 */
void testSscanf()
{
    int year, day;
    char weekday[20], month[20], dtm[20];
    strcpy(dtm, "Saturday March 25 1989");
    sscanf(dtm, "%s %s %d %d", weekday, month, &day, &year);
    printf("-------------sscanf 测试--------------------\n");
    printf("%s %d %d=%s\n", month, day, year, weekday);
}

/**
* 结构体
 * 结构体定义由关键字 struct 和结构体名组成，结构体名可以根据需要自行定义。

struct 语句定义了一个包含多个成员的新的数据类型，struct 语句的格式如下：

struct tag {
    member-list
    member-list
    member-list
    ...
} variable-list ;
*/

struct books
{
    char title[50];
    char author[50];
    char subject[100];
    int book_id;

} book;

struct
{
    int a;
    char b;
    double c;
} s1;

struct simple
{
    int a;
    char b;
    double c;
};
//用SIMPLE标签的结构体，另外声明了变量t1、t2、t3
struct simple t1, t2[20], t3;

